package com.dubious.interview.euler.prime;

import java.util.Iterator;

/**
 * Describes an iterator of primes.  Admittedly there is nothing about this
 * interface that ensures its implementations return only primes.
 */
public abstract class PrimeIterator implements Iterator<Long>, Iterable<Long>
{

    private boolean returnedLastPrime = true;
    private long lastPrime = 1;
    
    // returns the next prime
    protected abstract long nextPrime();
    
    protected long getLastPrime()
    {
        return lastPrime;
    }
    
    @Override
    public boolean hasNext() {
        // if last prime has been generated but not returned, it means it is waiting to be next
        if(!returnedLastPrime) return true;
        
        // generate the next prime, if it does not exist, there is nothing left
        long nextPrime = nextPrime();
        if(nextPrime == 0) return false;
        
        // save the next prime and indicate it has not yet been returned
        lastPrime = nextPrime;
        returnedLastPrime = false;
        return true;
    }

    @Override
    public Long next() {
        // if last prime has been generated but not yet returned, then we should return it
        if(!returnedLastPrime) {
            returnedLastPrime = true;
            return lastPrime;
        }
        
        // generate the next prime, if it does not exist return 0
        long nextPrime = nextPrime();
        if(nextPrime == 0) return 0L;
        
        // save the next prime and return it
        lastPrime = nextPrime;
        returnedLastPrime = true;
        return lastPrime;
    }
    
    @Override
    public void remove() {
        throw new UnsupportedOperationException("Cannot remove primes.  They are governed by laws of the universe.");
    }

    @Override
    public Iterator<Long> iterator() {
        return this;
    }
}
